import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;


public class DecisionMaker {
	// the number of features
	public static int NUM_FEATURES = 5;
	
	private ArrayList<Stateview> states;
	private Stateview curState;
	
	// height-related features
	private HeightMeanFeature heightMeanF;
	private HeightDiffFeature heightDiffF;
	private CliffFeature cliffF;
	
	// hole related feature
	private HoleCountFeature holeCntF;
	private HoleBurialFeature holeBurialF;
	private HoleSizeFeature holeSizeF;
	private HolePerRowFeature holeRowF;
	
	// reward feature
	private RowsClearFeature rowsClearF;
	private double[] score=new double[NUM_FEATURES];
	public double[] omega=new double[NUM_FEATURES];
	
	public DecisionMaker(ArrayList<Stateview> s_list) {
		// copy states array address
		int count = 0;
		/*
		for(int i=0; i<NUM_FEATURES;i++){
			omega[i]=1;
		}*/
		
		Scanner sc;
		try {
			sc = new Scanner(new File("omega.txt"));
			//System.out.println(sc.nextLine());
			omega[count++] = 0.5655362014133732;
			omega[count++] = 0.1804422091068085;
			omega[count++] = 0.03841691726722294;
			//omega[count++] = Math.abs(sc.nextDouble());
			omega[count++] = 0.16391088516898622;
			omega[count++] = 0.22008831877830093;
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		/*omega[0]=1.5;
		omega[1]=1.5;
		omega[2]=1.5;
		omega[3]=1.5;
		omega[4]=1;
		omega[5]=1;
		omega[6]=1.5;*/
		states = s_list;
		
		heightMeanF = new HeightMeanFeature();
		heightDiffF = new HeightDiffFeature();
		cliffF = new CliffFeature();
		
		holeCntF = new HoleCountFeature();
		holeBurialF = new HoleBurialFeature();
		holeSizeF = new HoleSizeFeature();
		holeRowF = new HolePerRowFeature();	
		
		rowsClearF = new RowsClearFeature();
	}
	
	// shallow copy
	public void setStates(ArrayList<Stateview> s_list) {
		states = s_list;
	}
	
	public void setCurState(Stateview cur) {
		curState = cur;
	}
	
	public int[] getDecision() {
		int move[] = new int[2];
		int score = -10000000;
		int key_value = 0;
		
		for(Stateview s : states) {
			int tmp = 0;	
			tmp += heightMeanF.computeScore(s);
			tmp += heightDiffF.computeScore(s);
			tmp += cliffF.computeScore(s);
			//System.out.println("Score of height: " + tmp);
			tmp += holeCntF.computeScore(s);
			//tmp += holeBurialF.computeScore(s);
			//tmp += holeSizeF.computeScore(s);
			//tmp += holeRowF.computeScore(s);
			tmp += rowsClearF.computeScore(s);
			//System.out.println("Score after penalty: " + tmp);
			
			
			if(score < tmp) {
				score = tmp;
				key_value = s.getStateValue();
			}
		}
		
		move[0] = key_value%100/10; // get slot
		move[1] = key_value/100; // get orientation
		
		//System.out.println("decision maker orient: " + move[0] + "; slot: " + move[1]);
		
		return move;
	}
	
	//yangzhaoyu
	//I need a method called compute score,this method will take in state s then compute all the features then
	//return me a int score
	public int computes(Stateview s){
		int tmp=0;
		int count = 0;
		tmp += omega[count++]*heightMeanF.computeScore(s);
		tmp += omega[count++]*heightDiffF.computeScore(s);
		tmp += omega[count++]*cliffF.computeScore(s);
		//System.out.println("Score of height: " + tmp);
		tmp += omega[count++]*holeCntF.computeScore(s);
		//tmp += omega[count++]*holeBurialF.computeScore(s);
		//tmp += omega[count++]*holeSizeF.computeScore(s);
		//tmp += omega[count++]*holeRowF.computeScore(s);
		tmp += omega[count++]*rowsClearF.computeScore(s);
		
		return tmp;
	}
	public double[] learncompute(Stateview s){
		int count = 0;
		
		score[count]= omega[count++]*heightMeanF.computeScore(s);
		score[count]= omega[count++]*heightDiffF.computeScore(s);
		score[count]= omega[count++]*cliffF.computeScore(s);
		//System.out.println("Score of height: " + tmp);
		score[count]= omega[count++]*holeCntF.computeScore(s);
		//score[count]= omega[count++]*holeBurialF.computeScore(s);
		//score[count]= omega[count++]*holeSizeF.computeScore(s);
		//score[count]= omega[count++]*holeRowF.computeScore(s);
		score[count]= omega[count++]*rowsClearF.computeScore(s);
		//System.out.println(score[0]);
		return score;
	}
	public void setOmega(double[] b){
		for(int i=0;i<NUM_FEATURES;i++){
			omega[i]=b[i];
			//System.out.println(i+" "+omega[i]);
		}
	}
	public int[] minimaxFunction(){
		int score[][] = new int[states.size()][3];

		//score[n][0]is the orient to score that score for piece n
		//score[n][1]is the slot to score that score for piece n
		//score[n][2]is the score for piece n

		//copy the state to temp state
		int i=0;
		for (Stateview s : states){
			
			score[i][0]= s.getStateValue()%100/10;
			score[i][1]= s.getStateValue()/100;
			score[i][2]=10000000;
			for(int k =0; k<Stateview.N_PIECES;k++){
				int tmpuse;
				int piece_type = k;
				Stateview tempstate = new Stateview();
				tempstate.setTop(s.getTop());
				tempstate.setField(s.getField());
				tempstate.setPiece(s.getNextPiece());
				
				tmpuse=computeFutureMove(piece_type,tempstate, tempstate.legalMoves(k));
				
				if(score[i][2]>tmpuse){
					score[i][2]=tmpuse;
				}
			}	
			i++;
		}
		int tmpuse = -10000000;
		int index = 0; 
		int k=0;
		for(Stateview s : states){
			if(score[k][2]>tmpuse){
				index = k;
				tmpuse=score[k][2];
				
			}
			k++;
		}
		int[]move=new int[2];

		if(states.size() > 0){
			move[0]=score[index][0];
			move[1]=score[index][1];
		} else {
			move[0]=0;
			move[1]=0;
		}
		
		
		return move;
	}


	public int computeFutureMove(int piecetype, Stateview s, int[][] legalMoves) {
		int slot=0, orient=0, weight=-10000000;
		
		for (int i=0; i<legalMoves.length;i++) {
			Stateview temp = new Stateview();
			temp.setTop(s.getTop());
			temp.setField(s.getField());
			temp.setPiece(s.getNextPiece());
			temp.myMakeMove(piecetype,legalMoves[i][0], legalMoves[i][1]);
			int tmp = computes(temp);
		
			if (weight < tmp) {
				weight = tmp;
			}		
		}
		//System.out.println(piecetype+" weight "+weight);
		return weight;
	}
	
	
	//yangzhaoyu

}
